package org.example;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.sl.usermodel.Placeholder;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.File;
import java.util.List;

public class PPTFormatChecker {

    private XMLSlideShow ppt;
    private List<XSLFSlide> slides;
    private int score = 0;
    private StringBuilder feedback = new StringBuilder();
    private StringBuilder debugInfo = new StringBuilder();

    public PPTFormatChecker(String filePath) {
        try {
            FileInputStream fis = new FileInputStream(new File(filePath));
            this.ppt = new XMLSlideShow(fis);
            this.slides = ppt.getSlides();
            fis.close();
            debugInfo.append("成功加载PPT，共").append(slides.size()).append("张幻灯片\n");
        } catch (IOException e) {
            feedback.append("无法打开PPT文件: ").append(e.getMessage());
        }
    }

    public void checkAllRequirements() {
        if (ppt == null) {
            feedback.append("PPT文件未正确加载，无法进行检查。\n");
            return;
        }

        // 先收集调试信息
        collectDebugInfo();

        checkFirstSlide();
        checkLastSlide();
        checkSecondSlide();
        checkThirdSlide();
        checkSlideTransition();
        checkDesignTemplate();

        feedback.append("\n最终得分: ").append(score).append("/100\n");
        feedback.append("\n=== 调试信息 ===\n").append(debugInfo.toString());
    }

    private void collectDebugInfo() {
        debugInfo.append("=== PPT结构分析 ===\n");

        for (int i = 0; i < slides.size(); i++) {
            XSLFSlide slide = slides.get(i);
            debugInfo.append("幻灯片 ").append(i + 1).append(":\n");

            // 布局信息
            XSLFSlideLayout layout = slide.getSlideLayout();
            debugInfo.append("  布局名称: ").append(layout.getName()).append("\n");

            // 形状信息
            List<XSLFShape> shapes = slide.getShapes();
            debugInfo.append("  形状数量: ").append(shapes.size()).append("\n");

            for (XSLFShape shape : shapes) {
                if (shape instanceof XSLFTextShape) {
                    XSLFTextShape textShape = (XSLFTextShape) shape;
                    String text = textShape.getText();
                    debugInfo.append("  文本形状: '").append(text != null ? text : "空").append("'\n");

                    // 详细检查字体信息
                    checkFontDetails(textShape, i + 1);

                    // 检查超链接
                    checkHyperlinkDetails(textShape, i + 1);
                } else if (shape instanceof XSLFPictureShape) {
                    debugInfo.append("  图片形状\n");
                }
            }
            debugInfo.append("\n");
        }
    }

    private void checkFontDetails(XSLFTextShape textShape, int slideNum) {
        try {
            for (XSLFTextParagraph paragraph : textShape.getTextParagraphs()) {
                for (XSLFTextRun textRun : paragraph.getTextRuns()) {
                    String fontFamily = textRun.getFontFamily();
                    Double fontSize = textRun.getFontSize();

                    debugInfo.append("    字体: ").append(fontFamily)
                            .append(", 大小: ").append(fontSize).append("\n");

                    // 特别记录最后一页的字体信息用于艺术字检查
                    if (slideNum == slides.size()) {
                        debugInfo.append("    → 最后一页字体信息记录\n");
                    }
                }
            }
        } catch (Exception e) {
            debugInfo.append("    检查字体时出错: ").append(e.getMessage()).append("\n");
        }
    }

    private void checkHyperlinkDetails(XSLFTextShape textShape, int slideNum) {
        // 检查形状级别的超链接
        if (textShape.getHyperlink() != null) {
            debugInfo.append("    形状超链接: ").append(textShape.getHyperlink().getAddress()).append("\n");
        }

        // 检查文本运行级别的超链接[1](@ref)
        try {
            for (XSLFTextParagraph paragraph : textShape.getTextParagraphs()) {
                for (XSLFTextRun textRun : paragraph.getTextRuns()) {
                    if (textRun.getHyperlink() != null) {
                        String address = textRun.getHyperlink().getAddress();
                        debugInfo.append("    文本运行超链接: '").append(textRun.getRawText())
                                .append("' -> ").append(address).append("\n");
                    }
                }
            }
        } catch (Exception e) {
            debugInfo.append("    检查超链接时出错: ").append(e.getMessage()).append("\n");
        }
    }

    private void checkFirstSlide() {
        if (slides.size() < 1) {
            feedback.append("❌ 幻灯片数量不足，无法检查第一张幻灯片。\n");
            return;
        }

        XSLFSlide firstSlide = slides.get(0);

        // 检查版式是否为标题幻灯片[4](@ref)
        XSLFSlideLayout layout = firstSlide.getSlideLayout();
        boolean isTitleSlide = false;
        try {
            String layoutName = layout.getName().toLowerCase();
            if (layoutName.contains("title") && layoutName.contains("slide")) {
                isTitleSlide = true;
            }
        } catch (Exception e) {
            // 通过占位符判断
            for (XSLFShape shape : firstSlide.getShapes()) {
                if (shape instanceof XSLFTextShape) {
                    XSLFTextShape textShape = (XSLFTextShape) shape;
                    if (textShape.getPlaceholder() != null) {
                        Placeholder placeholder = textShape.getPlaceholder();
                        if (placeholder == Placeholder.TITLE || placeholder == Placeholder.SUBTITLE) {
                            isTitleSlide = true;
                            break;
                        }
                    }
                }
            }
        }

        if (isTitleSlide) {
            score += 10;
            feedback.append("✅ 第一张幻灯片版式正确（标题幻灯片）。\n");
        } else {
            feedback.append("❌ 第一张幻灯片版式不正确，应为标题幻灯片。\n");
        }

        // 检查标题和副标题文本内容
        boolean titleFound = false;
        boolean subtitleFound = false;

        for (XSLFShape shape : firstSlide.getShapes()) {
            if (shape instanceof XSLFTextShape) {
                XSLFTextShape textShape = (XSLFTextShape) shape;
                String text = textShape.getText();
                if (text != null) {
                    if (text.contains("北京古迹旅游简介")) {
                        titleFound = true;
                    }
                    if (text.contains("北京市旅游发展委员会")) {
                        subtitleFound = true;
                    }
                }
            }
        }

        if (titleFound && subtitleFound) {
            score += 10;
            feedback.append("✅ 第一张幻灯片标题和副标题内容正确。\n");
        } else {
            if (!titleFound) feedback.append("❌ 未找到标题'北京古迹旅游简介'\n");
            if (!subtitleFound) feedback.append("❌ 未找到副标题'北京市旅游发展委员会'\n");
        }
    }

    private void checkLastSlide() {
        if (slides.size() < 1) {
            feedback.append("❌ 幻灯片数量不足，无法检查最后一张幻灯片。\n");
            return;
        }

        XSLFSlide lastSlide = slides.get(slides.size() - 1);

        // 检查是否为空白版式
        XSLFSlideLayout layout = lastSlide.getSlideLayout();
        boolean isBlankLayout = false;
        try {
            String layoutName = layout.getName().toLowerCase();
            if (layoutName.contains("blank")) {
                isBlankLayout = true;
            }
        } catch (Exception e) {
            // 通过形状数量判断
            if (lastSlide.getShapes().size() <= 2) {
                isBlankLayout = true;
            }
        }

        if (isBlankLayout) {
            score += 5;
            feedback.append("✅ 最后一张幻灯片版式正确（空白版式）。\n");
        } else {
            feedback.append("❌ 最后一张幻灯片版式不正确，应为空白版式。\n");
        }

        // 增强的艺术字检查：包括字体大小检查[1](@ref)
        boolean hasCorrectArtText = false;
        boolean hasText = false;

        for (XSLFShape shape : lastSlide.getShapes()) {
            if (shape instanceof XSLFTextShape) {
                XSLFTextShape textShape = (XSLFTextShape) shape;
                if (textShape.getText() != null && !textShape.getText().trim().isEmpty()) {
                    hasText = true;

                    // 检查字体大小是否为80磅[1](@ref)
                    if (checkFontSize80(textShape)) {
                        hasCorrectArtText = true;
                        score += 10; // 字体大小正确得分
                        feedback.append("✅ 最后一张幻灯片艺术字字体大小正确（80磅）。\n");
                        break;
                    }
                }
            }
        }

        if (hasText) {
            score += 5;
            feedback.append("✅ 最后一张幻灯片包含文本内容（艺术字初步检查通过）。\n");
        } else {
            feedback.append("❌ 最后一张幻灯片未找到文本内容。\n");
        }

        if (!hasCorrectArtText && hasText) {
            feedback.append("❌ 艺术字字体大小不是80磅。\n");
        }
    }

    private boolean checkFontSize80(XSLFTextShape textShape) {
        try {
            for (XSLFTextParagraph paragraph : textShape.getTextParagraphs()) {
                for (XSLFTextRun textRun : paragraph.getTextRuns()) {
                    Double fontSize = textRun.getFontSize();
                    // 检查字体大小是否为80磅（允许一定的误差）
                    if (fontSize != null && Math.abs(fontSize - 80.0) < 1.0) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
            debugInfo.append("检查字体大小时出错: ").append(e.getMessage()).append("\n");
        }
        return false;
    }

    private void checkSecondSlide() {
        if (slides.size() < 2) {
            feedback.append("❌ 幻灯片数量不足，无法检查第二张幻灯片。\n");
            return;
        }

        XSLFSlide secondSlide = slides.get(1);
        boolean tiantanFound = false;
        boolean hasHyperlink = false;
        boolean correctLink = false;

        for (XSLFShape shape : secondSlide.getShapes()) {
            if (shape instanceof XSLFTextShape) {
                XSLFTextShape textShape = (XSLFTextShape) shape;
                String text = textShape.getText();
                if (text != null && text.contains("天坛")) {
                    tiantanFound = true;

                    // 改进的超链接检查[1](@ref)
                    String linkAddress = checkHyperlinkExists(textShape);
                    if (linkAddress != null) {
                        hasHyperlink = true;
                        // 检查是否链接到第六张幻灯片
                        if (slides.size() >= 6 && isLinkToSlide6(linkAddress)) {
                            correctLink = true;
                            score += 10;
                            feedback.append("✅ '天坛'超链接正确指向第六张幻灯片。\n");
                        } else {
                            feedback.append("⚠️ '天坛'有超链接，但可能未指向第六张幻灯片: ").append(linkAddress).append("\n");
                        }
                    }
                }
            }
        }

        if (tiantanFound) {
            score += 5;
            feedback.append("✅ 第二张幻灯片包含'天坛'文本。\n");
        } else {
            feedback.append("❌ 第二张幻灯片未找到'天坛'文本。\n");
        }

        if (!hasHyperlink) {
            feedback.append("❌ 未找到'天坛'的超链接。\n");
        } else if (!correctLink) {
            feedback.append("⚠️ 超链接存在，但目标可能不是第六张幻灯片。\n");
        }

        // 动画效果无法直接检查
        feedback.append("⚠️ 动画效果（回旋）无法通过程序自动检查，需人工确认。\n");
    }

    private String checkHyperlinkExists(XSLFTextShape textShape) {
        // 检查形状级别的超链接
        if (textShape.getHyperlink() != null) {
            return textShape.getHyperlink().getAddress();
        }

        // 检查文本运行级别的超链接[1](@ref)
        try {
            for (XSLFTextParagraph paragraph : textShape.getTextParagraphs()) {
                for (XSLFTextRun textRun : paragraph.getTextRuns()) {
                    if (textRun.getHyperlink() != null) {
                        return textRun.getHyperlink().getAddress();
                    }
                }
            }
        } catch (Exception e) {
            debugInfo.append("检查超链接时出错: ").append(e.getMessage()).append("\n");
        }

        return null;
    }

    private boolean isLinkToSlide6(String linkAddress) {
        if (linkAddress == null) return false;

        // 检查各种可能的链接格式
        return linkAddress.contains("6") ||
                linkAddress.contains("slide6") ||
                linkAddress.contains("#6") ||
                linkAddress.toLowerCase().contains("six");
    }

    private void checkThirdSlide() {
        if (slides.size() < 3) {
            feedback.append("❌ 幻灯片数量不足，无法检查第三张幻灯片。\n");
            return;
        }

        XSLFSlide thirdSlide = slides.get(2);

        // 检查版式是否为两栏内容
        XSLFSlideLayout layout = thirdSlide.getSlideLayout();
        boolean isTwoContent = false;
        try {
            String layoutName = layout.getName().toLowerCase();
            if ((layoutName.contains("two") && layoutName.contains("content")) ||
                    (layoutName.contains("2") && layoutName.contains("content"))) {
                isTwoContent = true;
            }
        } catch (Exception e) {
            // 通过占位符数量判断
            int bodyPlaceholderCount = 0;
            for (XSLFShape shape : thirdSlide.getShapes()) {
                if (shape instanceof XSLFTextShape) {
                    XSLFTextShape textShape = (XSLFTextShape) shape;
                    if (textShape.getPlaceholder() == Placeholder.BODY) {
                        bodyPlaceholderCount++;
                    }
                }
            }
            if (bodyPlaceholderCount >= 2) {
                isTwoContent = true;
            }
        }

        if (isTwoContent) {
            score += 10;
            feedback.append("✅ 第三张幻灯片版式正确（两栏内容）。\n");
        } else {
            feedback.append("❌ 第三张幻灯片版式不正确，应为两栏内容。\n");
        }

        // 检查图片
        boolean hasPicture = false;
        for (XSLFShape shape : thirdSlide.getShapes()) {
            if (shape instanceof XSLFPictureShape) {
                hasPicture = true;
                break;
            }
        }

        if (hasPicture) {
            score += 10;
            feedback.append("✅ 第三张幻灯片包含图片。\n");
        } else {
            feedback.append("❌ 第三张幻灯片未找到图片。\n");
        }

        // 动画效果无法直接检查
        feedback.append("⚠️ 图片动画效果（百叶窗）无法通过程序自动检查，需人工确认。\n");
    }

    private void checkSlideTransition() {
        boolean allHaveTransition = false;
        int transitionCount = 0;

        try {
            for (XSLFSlide slide : slides) {
                CTSlide ctSlide = slide.getXmlObject();
                if (ctSlide.isSetTransition()) {
                    transitionCount++;
                }
            }

            if (transitionCount == slides.size()) {
                allHaveTransition = true;
            }
        } catch (Exception e) {
            // 简化检查
            if (slides.size() >= 5) {
                allHaveTransition = true;
                transitionCount = slides.size();
            }
        }

        if (allHaveTransition && transitionCount == slides.size()) {
            score += 10;
            feedback.append("✅ 所有幻灯片都设置了切换方式。\n");
        } else {
            feedback.append("❌ 部分幻灯片未设置切换方式。\n");
        }

        feedback.append("⚠️ 切换方式具体类型（水平百叶窗）无法通过程序自动检查，需人工确认。\n");
    }

    private void checkDesignTemplate() {
        List<XSLFSlideMaster> slideMasters = ppt.getSlideMasters();
        if (slideMasters != null && !slideMasters.isEmpty()) {
            score += 10;
            feedback.append("✅ 检测到设计模板已应用。\n");
        } else {
            feedback.append("❌ 未检测到设计模板应用。\n");
        }
    }

    public int getScore() {
        return score;
    }

    public String getFeedback() {
        return feedback.toString();
    }

    public void close() throws IOException {
        if (ppt != null) {
            ppt.close();
        }
    }

    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.println("请提供PPT文件路径作为参数");
            return;
        }

        PPTFormatChecker checker = new PPTFormatChecker(args[0]);
        checker.checkAllRequirements();
        System.out.println("检查完成！");
        System.out.println(checker.getFeedback());

        try {
            checker.close();
        } catch (IOException e) {
            System.out.println("关闭文件时出错: " + e.getMessage());
        }
    }
}